<?php
/**
 * @package Curly
 * @version 0.9
 * @link http://curly.codeplex.com/
 * @license http://curly.codeplex.com/license The MIT License
 * @author Dawid Zawada
 */

namespace Curly
{
	use Curly\Adapters\Adapter;
	use Curly\Collections\Collection;
	use Curly\Exceptions\CurlyException;

	/**
	 * Base class for HttpClient adapters
	 * 
	 * @package Curly
	 * @license http://curly.codeplex.com/license The MIT License
	 */
	abstract class HttpClient
    {
        /**
	     * Path of the automatically created cookie jar file
	     * 
	     * The jar file is created in the systems temp directory and
	     * is deleted when this object is destroyed
	     * 
	     * @var string
	     */
	    protected $autoJarFilePath;
	    
	    /**
	     * Collection of default options (used by client adapters)
	     * 
	     * @var Curly\Collections\Collection
	     */
        protected $defaultOptions;
        
        /**
         * Indication of whether the HTTP client is working
         * 
         * @var bool
         */
        protected $isExecuting;
        
        /**
         * Array of attached requests
         * 
         * @var array
         */
        protected $requests = array();
        
        /**
         * Array of finished requests
         * 
         * @var array
         */
        protected $finishedRequests = array();
        
        /**
         * Initializes the default options collection
         */
        public function __construct()
        {
            $this->defaultOptions = new Collection();
        }
        
        /**
         * Removes the automatically created cookie jar file if created
         */
        public function __destruct()
        {
            if( $this->getAutoJarFilePath() != "" )
            {
                unlink( $this->getAutoJarFilePath() );
            }
        }
        
        /**
         * Returns the path of the automatically created cookie jar file
         *
         * The jar file is created in the systems temp directory and
	     * is deleted when this object is destroyed
         *
         * @return string
         */
        public function getAutoJarFilePath()
        {
            if( empty( $this->autoJarFilePath ) )
	        {
	            $this->autoJarFilePath = tempnam( sys_get_temp_dir(), "CookieJar_" );
	        }
	        
	        return $this->autoJarFilePath;
        }
        
        /**
         * Returns the collection of default options
         *
         * @return Curly\Collections\Collection
         */
        public function defaultOptions()
        {
            return $this->defaultOptions;
        }
        
        /**
         * Returns indication of whether the HTTP client is working
         *
         * @return bool
         */
        public function isExecuting()
        {
            return $this->isExecuting;
        }
        
        /**
         * Sets indication of whether the HTTP client is working
         * 
         * @param bool $isExecuting
         */
        protected function setExecuting( $isExecuting )
        {
            $this->isExecuting = (bool)$isExecuting;
        }
        
        /**
         * Attaches the given Request object to this HTTP client
         * 
         * @param Curly\Request $request
         */
        public function attach( Request $request )
        {
            $this->requests[] = $request;
        }
        
        /**
         * Detaches the given Request object from this HTTP client
         * 
         * The method returns true if the request detached successfully, false otherwise
         * 
         * @param Curly\Request $request
         * @return bool
         */
        public function detach( Request $request )
        {
            $key = array_search( $request, $this->requests );
            if( $key !== false )
            {
                unset( $this->requests[$key] );
                return true;
            }
            else
            {
                return false;
            }
        }
        
        /**
         * Returns an array of the attached Request objects
         *
         * @return array
         */
        public function getAttachedRequests()
        {
            return $this->requests;
        }
        
        /**
         * Indicates whether the client has at least one attached Request object
         *
         * @return bool
         */
        protected function hasAttachedRequests()
        {
            return !empty( $this->requests );
        }
        
        /**
         * Removes all attached Request objects from the client
         */
        public function clearAttachedRequests()
        {
            $this->requests = array();
        }
        
        /**
         * Returns an array of the finished Request objects
         *
         * @return array
         */
        public function getFinishedRequests()
        {
            return $this->finishedRequests;
        }
        
        /**
         * Removes all finished Request objects from the client
         */
        public function clearFinishedRequests()
        {
            $this->finishedRequests = array();
        }
        
        /**
         * Executes attached requests in parallel
         */
        abstract public function execute();
        
        /**
         * Creates and returns an object of one of HttpClient adapters basing 
         * on the $adapter parameter
         * 
         * If the parameter is not specified the method will create and return
         * an object of the most suitable adapter.
         * If no adapter can be created the method will throw an exception.
         * 
         * @param Curly\Adapters\Adapter $adapter
         * @return Curly\HttpClient
         * @throws Curly\Exceptions\CurlyException
         */
        public static function create( Adapter $adapter = null )
        {
            switch( $adapter )
            {
                case Adapter::CURL(): return new Adapters\CurlHttpClient();
                
                default: return self::getDefaultClient();
            }
        }
        
        /**
         * Returns an object of the most suitable HttpClient adapter
         * 
         * If no adapter can be created the method will throw an exception
         *
         * @return Curly\HttpClient
         * @throws Curly\Exceptions\CurlyException
         */
        private static function getDefaultClient()
        {
            if( function_exists( "curl_init" ) )
            {
                return new Adapters\CurlHttpClient();
            }
            
            throw new CurlyException( "No adapter can be created, check the libraby requirements" );
        }
        
        /**
         * Returns the version number of the Curly library
         *
         * @return string
         */
        public static function getVersion()
        {
            return "0.9";
        }
    }
}